package com.ruoyi.common.utils;

import java.util.HashMap;
import java.util.Map;

public class DistanceUtils {

    private static final double EARTH_RADIUS = 6371000; // 平均半径,单位：m；不是赤道

    /**
     * 计算指定公里的经纬度范围
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param dis       查找的范围，千米
     * @return
     */
    public static Map<String, Double> getPeopleNearby(double longitude, double latitude, double dis) {
        //先计算查询点的经纬度范围
        //longitude经度
        //latitude纬度
        double r = 6371;//地球半径 千米
        double dlng = 2 * Math.asin(Math.sin(dis / (2 * r)) / Math.cos(latitude * Math.PI / 180));
        dlng = dlng * 180 / Math.PI;//角度转为弧度
        double dlat = dis / r;
        dlat = dlat * 180 / Math.PI;
        double minlat = latitude - dlat;
        double maxlat = latitude + dlat;
        double minlng = longitude - dlng;
        double maxlng = longitude + dlng;
        HashMap<String, Double> map = new HashMap<>();
        map.put("minLongitude", minlng);
        map.put("maxLongitude", maxlng);
        map.put("minLatitude", minlat);
        map.put("maxLatitude", maxlat);
        return map;
    }

    /**
     * 获取2个经纬度的距离
     *
     * @param lng1 经度1
     * @param lat1 纬度1
     * @param lng2 经度2
     * @param lat2 纬度2
     * @return
     */
    public static double getDistance(Double lng1, Double lat1, Double lng2, Double lat2) {
        // 经纬度（角度）转弧度。弧度用作参数，以调用Math.cos和Math.sin
        // A经弧度
        double radiansAX = Math.toRadians(lng1);
        // A纬弧度
        double radiansAY = Math.toRadians(lat1);
        // B经弧度
        double radiansBX = Math.toRadians(lng2);
        // B纬弧度
        double radiansBY = Math.toRadians(lat2);
        double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX)
            + Math.sin(radiansAY) * Math.sin(radiansBY);
        // 反余弦值
        double acos = Math.acos(cos);
        // 最终结果
        return EARTH_RADIUS * acos;
    }

    /**
     * 获取2个经纬度的距离
     *
     * @param lon1 第一点的经度
     * @param lat1 第一点的纬度
     * @param lon2 第二点的经度
     * @param lat2 第二点的纬度
     * @return 返回的距离，单位 m
     */
    public static double getDistances(double lon1, double lat1, double lon2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lon1) - rad(lon2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }


    /**
     * 获取2个经纬度的距离,直接转为文本格式
     *
     * @param lon1 第一点的经度
     * @param lat1 第一点的纬度
     * @param lon2 第二点的经度
     * @param lat2 第二点的纬度
     * @return 返回的距离，单位 m
     */
    public static String getDistancesText(double lon1, double lat1, double lon2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lon1) - rad(lon2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        int distance = (int) s;
        if (distance > 1000) {
            return distance / 1000 + 1 + "公里以内";
        } else {
            return distance / 100 * 100 + "米以内";
        }
    }

    /**
     * 把距离[米]转为微信的距离格式
     *
     * @param distance 米
     * @return
     */
    public static String distancesText(int distance) {
        if (distance <= 10) {
            return "10米以内";
        }
        if (distance > 1000) {
            return distance / 1000 + 1 + "公里以内";
        } else {
            return distance + "米以内";
        }
    }

    /**
     * 转化为弧度(rad)
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }
}
